package com.gitee.form_token.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gitee.form_token.common.Const;
import com.gitee.form_token.common.RedisUtil;
import com.gitee.form_token.common.Result;
import com.gitee.form_token.common.ValueUtil;
import com.gitee.form_token.dto.LoginDto;
import com.gitee.form_token.entity.AppUser;
import com.gitee.form_token.service.AppUserService;
import com.gitee.form_token.token.CheckAppToken;
import com.gitee.form_token.token.JwtUtil;
import com.gitee.form_token.token.TokenDto;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.map.MapUtil;
import cn.hutool.crypto.SecureUtil;
import com.google.code.kaptcha.Producer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: Saturn
 * @dete: 2024-09-21 0:31
 **/
@Slf4j
@RestController
@RequestMapping("/app")
public class AppLoginController {

    @Resource
    private Producer producer;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private AppUserService appUserService;

    // 验证码
    @GetMapping({"/logout"})
    public Result logout(HttpServletRequest request) {

        // Token校验
        String username = CheckAppToken.getSubject(request);
        String redisKey = "app_" + username;

        redisUtil.del(redisKey);

        return Result.fail("登出成功");
    }

    // 验证码
    @GetMapping({"/captcha"})
    public Result captcha() throws IOException {

        // 生成 base64
        BASE64Encoder base64 = new BASE64Encoder();

        // 字节数组输出流
        ByteArrayOutputStream baoStream = new ByteArrayOutputStream();

        // 生成/输出图片
        String code = producer.createText();
        BufferedImage image = producer.createImage(code);

        ImageIO.write(image, "png", baoStream);
        String base64Img = "data:image/png;base64," + base64.encode(baoStream.toByteArray());

        String uuid = UUID.randomUUID().toString();
        redisUtil.set(uuid, code, 120);
        log.info("生成验证码 code：{}，key：{}", code, uuid);

        return Result.success(MapUtil.builder()
                .put("uuid", uuid)
                .put("base64Img", base64Img)
                .build()
        );
    }

    // 用户登录
    @PostMapping("/login")
    public Result appLogin(@Valid @RequestBody LoginDto loginDto) {
        /****************************** 验证码 start ******************************/

        String code = loginDto.getCode();
        String uuid = loginDto.getUuid();

        if (code == null || uuid == null) {
            return Result.fail("验证码为空");
        }

        String login_code = (String) redisUtil.get(uuid);
        log.info("验证码校验 code：{}，key：{}", code, uuid);

        if (!code.equals(login_code)) {
            return Result.fail("验证码错误");
        }

        /****************************** 验证码 end ******************************/

        String username = loginDto.getUsername();
        String password = loginDto.getPassword();

        if (username == null || password == null) {
            return Result.fail(Const.loginNullMsg);
        }

        // 清除验证码
        redisUtil.del(uuid);

        /****************************** 用户登录 start ******************************/

        AppUser appUser = appUserService.login(loginDto);

        // 生成令牌
        TokenDto subject = new TokenDto();
        subject.setUser(appUser.getUsername());
        subject.setUid(appUser.getId());
        subject.setRid(0L);
        String token = JwtUtil.createToken(subject, Const.AppIssuerKey);

        // 写入缓存
        String redisKey = "app_" + appUser.getUsername();
        redisUtil.set(redisKey, appUser, ValueUtil.redisExpire);

        /****************************** 用户登录 end ******************************/

        // 返回数据
        HashMap<Object, Object> userInfo = new HashMap<>();
        Map<String, Object> resData = new HashMap<>();

        userInfo.put("tel", appUser.getTel());
        userInfo.put("avatar", appUser.getAvatar());
        userInfo.put("userName", appUser.getUsername());

        resData.put("userinfo", userInfo);
        resData.put("token", token);

        return Result.success(resData);
    }

    // 用户注册
    @PostMapping("/register")
    public Result appRegister(@Valid @RequestBody LoginDto loginDto) {

        /****************************** 验证码 start ******************************/

        String code = loginDto.getCode();
        String uuid = loginDto.getUuid();

        if (code == null || uuid == null) {
            return Result.fail("验证码为空");
        }

        String login_code = (String) redisUtil.get(uuid);
        log.info("验证码校验 code：{}，key：{}", code, uuid);

        if (!code.equals(login_code)) {
            return Result.fail("验证码错误");
        }

        // 清除验证码
        redisUtil.del(uuid);

        /****************************** 验证码 end ******************************/

        String username = loginDto.getUsername();
        String password = loginDto.getPassword();

        if (username == null || password == null) {
            return Result.fail(Const.loginNullMsg);
        }

        /****************************** 用户注册 start ******************************/

        // 数据库 -- 账号校验
        long count = appUserService.count(new QueryWrapper<AppUser>().eq("username", username));
        if (count > 0) {
            return Result.fail("账号已存在");
        }

        AppUser user = new AppUser();
        user.setUsername(username);
        user.setPassword(SecureUtil.md5(password));
        user.setCreated(LocalDateTime.now());

        appUserService.save(user);

        /****************************** 用户注册 end ******************************/

        return Result.success();
    }

}
